/**	@file Utilities.h
 * @brief Taylor series, expansion and some other useful functionality.*/
#ifndef Utilities_h_majdo_sympy_cpp
#define Utilities_h_majdo_sympy_cpp
#include <vector>
#include "Ex.h"
namespace sympycpp {
class Ex;
class Expr;
class Sym;
class Add;
class Number;
/**	@class Utilities
 * 	@brief Encapsulation of auxiliary functions.
 * 	Some manipulations change structures of expressions too much.
 * 	Implentation these functions as member functions is not goot solution.
 * 	The functionality as the comparison, substitution and construction of expressions 
 * 	have own classes (clsses ComparerIx, Substitution, Operation). 
 * 	The others belong to this class.*/
class Utilities{
public:
	/**	@brief Taylor series.
	 * 	@param f is an approximated function
	 * 	@param fSeries Taylor series.
	 * 	@param byVar is a variable. Function is differentiated with respect to this variable.
	 * 	@param val is a point of evaluating.
	 * 	@param n is maximal allowed differentiation. */
	static void taylor(const Ex * f, Ex * & fSeries, const Sym * byVar, const Ex * val, const int n);
	/**	@brief Transformation of an expression into <0,2pi). 
	 *	This function is useful for goniometric functions.
	 * 	@param e is the transformed expression.
	 * 	@param t gives information whether the expression belongs to <0,2pi)
	 * 	@see set0_2Pi(const Expr &, bool &), an alternative transformation*/
	static void set0_2Pi(Ex * & e, bool & t);
	/**	@brief Transformation of an expression into <0,2pi). 
	 *	This function is useful for goniometric functions.
	 * 	@param e is the transformed expression.
	 * 	@param t gives information whether the expression belongs to <0,2pi)

	 * 	@see set0_2Pi(const Ex * &, bool &), an alternative transformation*/
	static Expr set0_2Pi(const Expr &, bool &);
	/**	@brief Expansion of expressions.
	 * 	@param Expanded expression.
	 * 	@param Count of nested multiplication that can be expanded.*/
	static bool expansion(Ex * & e, const int i);
	/**	@brief Special constructor of additions.
	 * 	This function constructs new expressions (sum of all elements in container). 
	 * 	@param v addends
	 * 	@param flag -> special memory management
	 * 	@see allocationPolicy : special memory management
	 * 	@warning This function returns new alocated memory that has to be deleted by user.*/
	static Ex * constructorAdd(basic_container &, const allocationPolicy flag);
private:
	/**	@brief Insert of new element into template of sources.
	 * 	This function inserts new element into the strucures that are generated by makeElements.
	 * 	@param i is new inserted element that can be joined with another already inserted elements
	 * 	@param src template
	 * 	@param help information about exponent and position
	 * 	@param index position of compatible element in the template src
	 * 	@see makeElements*/
	static void adderHELP(const_iterator i, std::vector<Ex *> & src,  std::vector<std::pair<int, Ex*> > & help, const int index);
	/**	@brief Insert of new element into template of sources.
	 * 	This function inserts (push back) new element into the strucures that are generated by makeElements.
	 * 	@param i is new inserted element that can not be joined with another already inserted elements
	 * 	@param src template
	 * 	@param help information about exponent and position
	 * 	@see makeElements*/
	static void adderSRC(const_iterator i, std::vector<Ex *> & src,  std::vector<std::pair<int, Ex*> > & help);
	/**	@brief Construction of a general template for addends.
	 * 	This function is auxiliary dunction for function multinomialTheorem. 
	 * 	It creastes general template of addends. Multinomila theorem transforms expression (a1+a2...)^n ---> (?)a1^?a2^?... .
	 * 	This functions creates templates as a1^?a2?... . The elemnts count in the addend is variable, order 
	 * 	from sum is not preserved and also simplifications can arise. 
	 * 	Consequently, the consequential tmplate <i>src</i> stores sorted and simplified expressions 
	 * 	(only bases of powers are strored if subexpressions (summands) were powers). 
	 * 	The information about exponents and position (because elements were reordering and some of them could be joined) is 
	 * 	returned in the next structure  <i>helpS</i>.
	 * 	@param p is container of summands that will transformed to multiplicands
	 * 	@param src is consequential template for construction multiplicative expressions
	 * 	@param helpS is auxiliary structure that has information about exponents  
	 * 	@see multinomialTheorem */
	static void makeElements(const basic_container & p, std::vector<Ex *> & src, std::vector<std::vector<std::pair<int, Ex*> > > & helpS);
	/**	@brief Construction of one addend of Multinomial Theorem.
	 * 	@param permutIndex is permautation of summands of the orginal expression
	 * 	@param src is tempate for generation of new multiplicative addends
	 * 	@param helpS additional information for <i>src</i>
	 * 	@param coef is multinomial coefficient
	 * 	@param hasher is simple hash table*/
	static Ex * makeAddend(const std::vector<int> & permutIndex, const std::vector<Ex *> & src, 
				const std::vector<std::vector<std::pair<int, Ex*> > > & helpS, const Number & coef, 
				const std::vector<int> & indexMultiplicity, const std::vector<int> & hasher);
	/**	@brief Multinomial coefficient.
	 * 	@see makeFactorials --> construction of table of factorials
	 * 	@see makePermut --> construction of the table of permutations
	 * 	@see multinomialTheorem --> Multinomial theorem
	 * 	@param p is permutation
	 * 	@param f is the table of factorials
	 * 	@param coef is computed multinomial coefficient */
	static void multinomCoef(const std::vector<int> & p, const std::vector<Number> & f, Number & coef);
	/**	@brief Construction of the table of factorials.
	 *	This function fills vector's elements with factorials of their indexes up to <i>max</i>.
	 *	@param max is maximal factorial
	 *	@param f is the table of generated factorials*/
	static void makeFactorials(const int max, std::vector<Number> & f);
	/**	@brief Construction of the table of sums. 
	 * 	This functions generates the table of all sums that are equal to<i>sum</i> and they consists of maximal <i>n</i> summands.
	 * 	It is resursive function used by makeSums.
	 * 	@see makeSums --> generation of the table of sums
	 *	@param pre is the previous generated sum
	 * 	@param res is the table of generated sums
	 * 	@param n is the maximal count of the summands
	 * 	@param sum is required sum of the generated elements */
	static void nextSum(std::vector<int> & pre, std::vector<std::vector<int> > & res, const int n, const int sum);
	/**	@brief Construction of the table of sums. 
	 * 	This functions generates the table of all sums that are equal to<i>sum</i> and they consists of maximal <i>n</i> summands.
	 * 	@param n is the maximal count of the summands
	 * 	@param sum is required sum of the generated elements 
	 * 	@param res is the table of generated sums*/
	static void makeSums(const int n, const int sum, std::vector<std::vector<int> > & res);
	/**	@brief Construstio of the table of permutations.
	 * 	This function generates all permutations from elements  of <i>s</i>. 
	 * 	@param n is length of permutation (missing elements are supplemented by 0)
	 * 	@param s is vector of permutated numbers 
	 * 	@param res is the table of permutations.*/
	static void makePermut(const int n, std::vector<int> & s,std::vector<std::vector<int> > & res);
	/**	@brief Multinomial theorem.
	 * 	@warning This function returns new alocated expression. Consequently the user is responsible for 
	 * 	dealocation of used memory. */
	static Ex * multinomialTheorem(const Add &, const Number &);
	/**	@brief Multiplication of the sequence of expressions.
	 * 	@param e is left multiplicand
	 * 	@param vMul is sequence of multiplicands
	 *	@param lebel is allowed count of multiplicated multiplications.*/
	static void multiplier(Ex * & e, basic_container * vMul, const int level);
	/**	@brief Special multiplication.
	 * 	The traditional multiplication does not expand additions. 
	 * 	This function do this.*/
	static Ex * multiplierPair(Ex * e1, Ex * e2, const int level); 
};
}
#endif
